package org.amse.korovkin.ciphering.model.cipher.splinewavelet;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.Scanner;
import org.amse.korovkin.ciphering.model.cipher.IKey;
import org.amse.korovkin.ciphering.model.cipher.util.MathUtil;

/**
 *
 * @author Mikhail Korovkin
 */
public class SplineKey implements IKey{
    private List<Integer> array;
    private List<Integer> striking;

    public SplineKey() {
        array = new ArrayList<Integer>();
        striking = new ArrayList<Integer>();
    }

    public int getRounds() {
        return striking.size();
    }
    public int removeElem(int index) {
        int buf = array.get(index % array.size());
        array.remove(index % array.size());
        return buf;
    }
    public int getElem(int index) {
        if (index < 0) {
            index = MathUtil.modul(index, array.size());
        }
        return array.get(index % array.size());
    }
    public void addElem(int index, int e) {
        array.add(index % (array.size()+1), e);
        striking.add(0,index);
    }
    public int nextNumber() {
        int buf = striking.get(0);
        striking.remove(0);
        return buf;
    }

    public void readFromFile(String inputFile) throws FileNotFoundException, IOException {
        Scanner scan = new Scanner(new FileReader(inputFile));
        int k = scan.nextInt();
        for (int i = 0; i < k; i++) {
            array.add(scan.nextInt());
        }
        int alpha = scan.nextInt();
        for (int i = 0; i < alpha; i++) {
            striking.add(scan.nextInt());
        }
        scan.close();
    }
    public void writeToFile(String outputFile) throws IOException {
        PrintWriter pWriter = new PrintWriter(outputFile);

        pWriter.println("" + array.size());
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < array.size(); i++) {
            sb.append("" +array.get(i));
            sb.append(" ");
        }
        pWriter.println(sb.toString());
        sb.delete(0, sb.length());

        pWriter.println("" + striking.size());
        for (int i = 0; i < striking.size(); i++) {
            sb.append("" + striking.get(i));
            sb.append(" ");
        }
        pWriter.println(sb.toString());
        pWriter.close();
    }

    @Override
    public String toString() {
        StringBuilder result = new StringBuilder();
        for (int i = 0; i < array.size(); i++) {
            result.append(array.get(i));
            result.append(' ');
        }
        result.append('\n');
        for (int i = 0; i < striking.size(); i++) {
            result.append(striking.get(i));
            result.append(' ');
        }
        return result.toString();
    }
    /*
     * DO override equals
     */
    @Override
    public SplineKey clone() {
        SplineKey clone = new SplineKey();
        List<Integer> cloneArr = new ArrayList<Integer>();
        List<Integer> cloneStr = new ArrayList<Integer>();
        for (int i = 0; i < array.size(); i++) {
            cloneArr.add(array.get(i));
        }
        for (int i = 0; i < striking.size(); i++) {
            cloneStr.add(striking.get(i));
        }
        clone.array = cloneArr;
        clone.striking = cloneStr;
        return clone;
    }

    public static void generate(int L, int K) {
        List<Integer> list = new ArrayList<Integer>();
        for (int i = 0; i < L; i++) {
            list.add(i);
        }
        Random r = new Random();
        SplineKey newKey = new SplineKey();
        for (int i = 0; i < L; i++) {
            int index = r.nextInt(L);
            int c = list.remove(index % list.size());
            int alpha = r.nextInt(L);
            newKey.addElem(alpha,c);
        }
        for (int i = 0; i < L-K; i++) {
            newKey.removeLastStriking();
        }
        try {
            newKey.writeToFile(IKey.KEY_PATH);
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
    private void removeLastStriking() {
        striking.remove(striking.size()-1);
    }
   
}
